package cn.edu.jxau.core.util;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;

/**
 * Desc:
 * ------------------------------------
 * Author:fulei04@meituan.com
 * Date:2017/12/15
 * Time:上午10:20
 */
public class ClassUtils {

    public static ClassLoader  getCurrentClassLoader() {
        return Thread.currentThread().getContextClassLoader();
    }

    public static Class<?> loadClass(String className, boolean isInit) throws ClassNotFoundException {

        try {
            return Class.forName(className,isInit,getCurrentClassLoader());
        } catch (ClassNotFoundException e) {
            throw new ClassNotFoundException(String.format("无法加载 %s 对应的Class对象",className),e);
        }
    }

    /**
     * 获取{@param packageName}指定包下的所有Class对象
     * @param packageName
     * @return
     */
    public static Set<Class<?>> getClassSet(String packageName) throws IOException, ClassNotFoundException {

        Set<Class<?>> set = new HashSet<>();
        Enumeration<URL> enumeration = getCurrentClassLoader().getResources(packageName.replace('.', File.separatorChar));
        while(enumeration.hasMoreElements()) {
            URL url = enumeration.nextElement();
            if(url == null) {
                continue ;
            }
            if(url.getProtocol().equals("file")) {
                String path = url.getPath().replace("%20","");
                addClass(set,path,packageName);
            } else if(url.getProtocol().equals("jar")) {
                throw new UnsupportedOperationException("暂不支持读取jar");
            } else {
                throw new IllegalStateException(String.format("暂不支持该url:%s",url));
            }
        }
        return set;
    }

    /**
     * 获取{@param path}路径下所有Class对象，全限定名用{@param packageName}拼装
     * @param path
     * @param packageName
     * @return
     */
    private static void addClass(Set<Class<?>> set,String path,String packageName) throws ClassNotFoundException {

        if(path == null || path.isEmpty()) {
            throw new IllegalArgumentException("参数path不可为空");
        }
        if(packageName == null || packageName.isEmpty()) {
            throw new IllegalArgumentException("参数packageName不可为空");
        }
        File[] fileArr = new File(path).listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.isDirectory() || pathname.getName().endsWith(".class");
            }
        });
        if(fileArr == null) {
            return ;
        }
        for(File file : fileArr) {
            if(file.isDirectory()) {
                String newPath = path+File.separator+file.getName();
                String newPackageName = packageName +"."+file.getName();
                addClass(set,newPath,newPackageName);
            } else {
                String className = packageName +"."+file.getName().substring(0,file.getName().lastIndexOf("."));
                set.add(loadClass(className,false));
            }
        }
    }
}
